"""
邮件发送服务
"""
import uuid
import json
import asyncio
from typing import List, Dict, Any, Optional
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_, func, desc
from jinja2 import Template, Environment, BaseLoader, TemplateError

from models.email_task import EmailTask, EmailSendRecord, EmailTaskStatus, EmailSendMode, EmailSendStatus
from models.email_template import EmailTemplate
from models.email_config import EmailConfig
from models.data_source import DataSource
from schemas.email_send import (
    EmailSendRequest, EmailSendResponse, EmailTaskCreate, EmailTaskUpdate,
    EmailSendRecordCreate, EmailSendRecordUpdate, EmailRecipient,
    EmailTaskList, EmailSendHistoryList, EmailStatistics,
    ContactImportRequest, ContactImportResponse,
    EmailPreviewRequest, EmailPreviewResponse
)
from services.email_service import EmailService
from services.data_source_field_service import DataSourceFieldService
from services.email_content_processor import EmailContentProcessor


class EmailSendService:
    """邮件发送服务"""

    @staticmethod
    def create_email_task(db: Session, request: EmailSendRequest, user_id: int) -> EmailSendResponse:
        """创建邮件发送任务"""
        try:
            # 生成任务ID
            task_id = str(uuid.uuid4())
            
            # 验证邮件配置
            email_config = db.query(EmailConfig).filter(
                EmailConfig.id == request.email_config_id,
                EmailConfig.user_id == user_id
            ).first()
            if not email_config:
                return EmailSendResponse(
                    success=False,
                    message="邮件配置不存在"
                )

            # 获取模板内容（如果使用模板）
            subject = request.subject
            content = request.content
            if request.template_id:
                template = db.query(EmailTemplate).filter(
                    EmailTemplate.id == request.template_id,
                    EmailTemplate.user_id == user_id
                ).first()
                if template:
                    subject = template.subject
                    content = template.content

            # 创建邮件任务
            task_data = EmailTaskCreate(
                subject=subject,
                content=content,
                template_id=request.template_id,
                email_config_id=request.email_config_id,
                send_mode=request.send_mode,
                send_immediately=request.send_immediately,
                scheduled_time=request.scheduled_time,
                recipients_config={
                    "recipients": [r.dict() for r in request.recipients]
                },
                template_variables=request.template_variables or {},
                attachments=request.attachments or []
            )

            db_task = EmailTask(
                id=task_id,
                **task_data.dict(),
                recipients_count=len(request.recipients),
                user_id=user_id
            )
            db.add(db_task)

            # 创建发送记录
            for recipient in request.recipients:
                record_id = str(uuid.uuid4())
                db_record = EmailSendRecord(
                    id=record_id,
                    task_id=task_id,
                    recipient_email=recipient.email,
                    recipient_name=recipient.name,
                    recipient_variables=recipient.variables or {}
                )
                db.add(db_record)

            db.commit()

            # 如果立即发送，启动发送任务
            if request.send_immediately:
                asyncio.create_task(EmailSendService._process_email_task(task_id))

            return EmailSendResponse(
                success=True,
                message="邮件任务创建成功",
                task_id=task_id,
                sent_count=0,
                failed_count=0
            )

        except Exception as e:
            db.rollback()
            return EmailSendResponse(
                success=False,
                message=f"创建邮件任务失败: {str(e)}"
            )

    @staticmethod
    async def _process_email_task(task_id: str):
        """处理邮件发送任务（异步）"""
        from database import SessionLocal
        db = SessionLocal()
        
        try:
            # 获取任务
            task = db.query(EmailTask).filter(EmailTask.id == task_id).first()
            if not task:
                return

            # 更新任务状态为运行中
            task.status = EmailTaskStatus.RUNNING
            task.started_at = datetime.utcnow()
            db.commit()

            # 获取邮件配置
            email_config = db.query(EmailConfig).filter(EmailConfig.id == task.email_config_id).first()
            if not email_config:
                task.status = EmailTaskStatus.FAILED
                task.error_message = "邮件配置不存在"
                task.completed_at = datetime.utcnow()
                db.commit()
                return

            # 获取发送记录
            send_records = db.query(EmailSendRecord).filter(
                EmailSendRecord.task_id == task_id,
                EmailSendRecord.status == EmailSendStatus.PENDING
            ).all()

            sent_count = 0
            failed_count = 0

            # 处理每个收件人
            for record in send_records:
                try:
                    # 渲染邮件内容
                    rendered_subject, rendered_content = EmailSendService._render_email_content(
                        db,
                        task.subject,
                        task.content,
                        record.recipient_variables or {},
                        task.template_variables or {},
                        task.user_id
                    )

                    # 更新记录的渲染内容
                    record.rendered_subject = rendered_subject
                    record.rendered_content = rendered_content

                    # 发送邮件
                    email_service = EmailService()
                    result = await email_service.send_email_async(
                        email_config=email_config,
                        to_email=record.recipient_email,
                        to_name=record.recipient_name,
                        subject=rendered_subject,
                        content=rendered_content,
                        attachments=task.attachments or []
                    )

                    if result["success"]:
                        record.status = EmailSendStatus.SENT
                        record.sent_at = datetime.utcnow()
                        record.message_id = result.get("message_id")
                        sent_count += 1
                    else:
                        record.status = EmailSendStatus.FAILED
                        record.error_message = result.get("error", "发送失败")
                        failed_count += 1

                except Exception as e:
                    record.status = EmailSendStatus.FAILED
                    record.error_message = str(e)
                    failed_count += 1

                db.commit()

            # 更新任务状态
            task.sent_count = sent_count
            task.failed_count = failed_count
            task.status = EmailTaskStatus.COMPLETED if failed_count == 0 else EmailTaskStatus.FAILED
            task.completed_at = datetime.utcnow()
            
            if failed_count > 0:
                task.error_message = f"部分邮件发送失败，成功: {sent_count}, 失败: {failed_count}"

            db.commit()

        except Exception as e:
            # 更新任务状态为失败
            task = db.query(EmailTask).filter(EmailTask.id == task_id).first()
            if task:
                task.status = EmailTaskStatus.FAILED
                task.error_message = str(e)
                task.completed_at = datetime.utcnow()
                db.commit()

        finally:
            db.close()

    @staticmethod
    def _render_email_content(db: Session, subject: str, content: str, recipient_vars: Dict[str, Any],
                            template_vars: Dict[str, Any], user_id: int) -> tuple:
        """渲染邮件内容"""
        try:
            # 首先处理动态表格标记
            processed_content = EmailContentProcessor.process_email_content(db, content, user_id)

            # 合并变量
            variables = {**template_vars, **recipient_vars}

            # 创建Jinja2环境
            env = Environment(loader=BaseLoader())

            # 渲染主题
            subject_template = env.from_string(subject)
            rendered_subject = subject_template.render(**variables)

            # 渲染内容
            content_template = env.from_string(processed_content)
            rendered_content = content_template.render(**variables)

            return rendered_subject, rendered_content

        except TemplateError as e:
            # 模板渲染错误，返回原始内容
            print(f"模板渲染错误: {str(e)}")
            return subject, content
        except Exception as e:
            # 其他错误，返回原始内容
            print(f"邮件内容渲染错误: {str(e)}")
            return subject, content

    @staticmethod
    def get_email_tasks(db: Session, user_id: int, page: int = 1, size: int = 10, 
                       status: Optional[EmailTaskStatus] = None, search: Optional[str] = None) -> EmailTaskList:
        """获取邮件任务列表"""
        query = db.query(EmailTask).filter(EmailTask.user_id == user_id)
        
        # 状态过滤
        if status:
            query = query.filter(EmailTask.status == status)
        
        # 搜索过滤
        if search:
            query = query.filter(EmailTask.subject.contains(search))
        
        # 总数
        total = query.count()
        
        # 分页
        offset = (page - 1) * size
        tasks = query.order_by(desc(EmailTask.created_at)).offset(offset).limit(size).all()
        
        # 计算总页数
        pages = (total + size - 1) // size
        
        return EmailTaskList(
            items=tasks,
            total=total,
            page=page,
            size=size,
            pages=pages
        )

    @staticmethod
    def get_email_task(db: Session, task_id: str, user_id: int) -> Optional[EmailTask]:
        """获取邮件任务详情"""
        return db.query(EmailTask).filter(
            EmailTask.id == task_id,
            EmailTask.user_id == user_id
        ).first()

    @staticmethod
    def cancel_email_task(db: Session, task_id: str, user_id: int) -> Dict[str, str]:
        """取消邮件任务"""
        task = db.query(EmailTask).filter(
            EmailTask.id == task_id,
            EmailTask.user_id == user_id
        ).first()
        
        if not task:
            return {"message": "任务不存在"}
        
        if task.status not in [EmailTaskStatus.PENDING, EmailTaskStatus.RUNNING]:
            return {"message": "任务无法取消"}
        
        task.status = EmailTaskStatus.CANCELLED
        task.completed_at = datetime.utcnow()
        db.commit()
        
        return {"message": "任务取消成功"}

    @staticmethod
    def get_email_send_history(db: Session, user_id: int, page: int = 1, size: int = 10,
                              task_id: Optional[str] = None, status: Optional[EmailSendStatus] = None,
                              search: Optional[str] = None) -> EmailSendHistoryList:
        """获取邮件发送历史"""
        query = db.query(EmailSendRecord).join(EmailTask).filter(EmailTask.user_id == user_id)
        
        # 任务ID过滤
        if task_id:
            query = query.filter(EmailSendRecord.task_id == task_id)
        
        # 状态过滤
        if status:
            query = query.filter(EmailSendRecord.status == status)
        
        # 搜索过滤
        if search:
            query = query.filter(
                or_(
                    EmailSendRecord.recipient_email.contains(search),
                    EmailSendRecord.rendered_subject.contains(search)
                )
            )
        
        # 总数
        total = query.count()
        
        # 分页
        offset = (page - 1) * size
        records = query.order_by(desc(EmailSendRecord.created_at)).offset(offset).limit(size).all()
        
        # 计算总页数
        pages = (total + size - 1) // size
        
        return EmailSendHistoryList(
            items=records,
            total=total,
            page=page,
            size=size,
            pages=pages
        )

    @staticmethod
    def get_email_statistics(db: Session, user_id: int) -> EmailStatistics:
        """获取邮件统计信息"""
        # 总任务数
        total_tasks = db.query(EmailTask).filter(EmailTask.user_id == user_id).count()
        
        # 总发送数和失败数
        total_sent = db.query(func.sum(EmailTask.sent_count)).filter(EmailTask.user_id == user_id).scalar() or 0
        total_failed = db.query(func.sum(EmailTask.failed_count)).filter(EmailTask.user_id == user_id).scalar() or 0
        
        # 成功率
        total_emails = total_sent + total_failed
        success_rate = (total_sent / total_emails * 100) if total_emails > 0 else 0
        
        # 今日发送数
        today = datetime.utcnow().date()
        today_sent = db.query(func.sum(EmailTask.sent_count)).filter(
            EmailTask.user_id == user_id,
            func.date(EmailTask.created_at) == today
        ).scalar() or 0
        
        # 本周发送数
        week_start = datetime.utcnow() - timedelta(days=7)
        this_week_sent = db.query(func.sum(EmailTask.sent_count)).filter(
            EmailTask.user_id == user_id,
            EmailTask.created_at >= week_start
        ).scalar() or 0
        
        # 本月发送数
        month_start = datetime.utcnow().replace(day=1)
        this_month_sent = db.query(func.sum(EmailTask.sent_count)).filter(
            EmailTask.user_id == user_id,
            EmailTask.created_at >= month_start
        ).scalar() or 0
        
        # 最近任务
        recent_tasks = db.query(EmailTask).filter(EmailTask.user_id == user_id)\
            .order_by(desc(EmailTask.created_at)).limit(5).all()
        
        return EmailStatistics(
            total_tasks=total_tasks,
            total_sent=total_sent,
            total_failed=total_failed,
            success_rate=round(success_rate, 2),
            today_sent=today_sent,
            this_week_sent=this_week_sent,
            this_month_sent=this_month_sent,
            recent_tasks=recent_tasks
        )

    @staticmethod
    def import_contacts(db: Session, request: ContactImportRequest, user_id: int) -> ContactImportResponse:
        """从数据源导入联系人"""
        try:
            # 查询数据源数据
            query_request = {
                "data_source_id": request.data_source_id,
                "table_name": request.table_name,
                "fields": [request.email_column] + ([request.name_column] if request.name_column else []) + (request.additional_columns or []),
                "filters": request.filters,
                "limit": 1000,  # 限制导入数量
                "offset": 0
            }

            # 使用数据源字段服务查询数据
            from schemas.data_source_field import DataSourceQuery
            query = DataSourceQuery(**query_request)
            preview = DataSourceFieldService.query_data_source_data(db, query, user_id)

            contacts = []
            failed_count = 0

            for row in preview.data:
                try:
                    email = row.get(request.email_column)
                    if not email or '@' not in email:
                        failed_count += 1
                        continue

                    name = row.get(request.name_column) if request.name_column else None
                    variables = {k: v for k, v in row.items() if k not in [request.email_column, request.name_column]}

                    contact = EmailRecipient(
                        email=email,
                        name=name,
                        variables=variables
                    )
                    contacts.append(contact)

                except Exception:
                    failed_count += 1
                    continue

            return ContactImportResponse(
                success=True,
                message=f"成功导入 {len(contacts)} 个联系人",
                imported_count=len(contacts),
                failed_count=failed_count,
                contacts=contacts
            )

        except Exception as e:
            return ContactImportResponse(
                success=False,
                message=f"导入联系人失败: {str(e)}",
                imported_count=0,
                failed_count=0,
                contacts=[]
            )

    @staticmethod
    def preview_email_content(db: Session, request: EmailPreviewRequest, user_id: int) -> EmailPreviewResponse:
        """预览邮件内容"""
        try:
            # 获取邮件内容
            subject = request.subject or ""
            content = request.content or ""

            if request.template_id:
                template = db.query(EmailTemplate).filter(
                    EmailTemplate.id == request.template_id,
                    EmailTemplate.user_id == user_id
                ).first()
                if template:
                    subject = template.subject
                    content = template.content

            # 准备变量
            variables = request.template_variables or {}
            if request.recipient and request.recipient.variables:
                variables.update(request.recipient.variables)

            # 渲染内容
            rendered_subject, rendered_content = EmailSendService._render_email_content(
                db, subject, content, request.recipient.dict() if request.recipient else {}, variables, user_id
            )

            # 分析变量使用情况
            env = Environment(loader=BaseLoader())

            # 提取使用的变量
            variables_used = []
            missing_variables = []

            try:
                subject_template = env.from_string(subject)
                content_template = env.from_string(content)

                # 获取模板中的变量
                subject_vars = subject_template.environment.parse(subject).find_all(env.nodes.Name)
                content_vars = content_template.environment.parse(content).find_all(env.nodes.Name)

                all_template_vars = set()
                for var in subject_vars:
                    all_template_vars.add(var.name)
                for var in content_vars:
                    all_template_vars.add(var.name)

                # 分类变量
                for var_name in all_template_vars:
                    if var_name in variables:
                        variables_used.append(var_name)
                    else:
                        missing_variables.append(var_name)

            except Exception:
                pass

            return EmailPreviewResponse(
                rendered_subject=rendered_subject,
                rendered_content=rendered_content,
                html_content=rendered_content,  # 假设内容是HTML
                variables_used=variables_used,
                missing_variables=missing_variables
            )

        except Exception as e:
            db.rollback() # 回滚事务
            return EmailPreviewResponse(
                rendered_subject=request.subject or "",
                rendered_content=request.content or "",
                html_content=request.content or "",
                variables_used=[],
                missing_variables=[]
            )
